using System;

namespace ICommonLibrary.Collection {

    [Serializable]
    public class LRUMap : SequencedHashMap {

        private int _maximumSize;

        public LRUMap()
            : this(100) { }

        public LRUMap(int capacity)
            : base(capacity) {
            _maximumSize = capacity;
        }

        public override object this[object key] {
            get {
                object result = base[key];
                if (result == null) return null;

                Remove(key);
                base.Add(key, result);
                return result;
            }
            set {
                Add(key, value);
            }
        }

        public override void Add(object key, object value) {
            int mapSize = Count;
            if (mapSize >= _maximumSize) {
                // don't retire LRU if you are just
                // updating an existing key
                if (!ContainsKey(key)) {
                    // lets retire the least recently used item in the cache
                    RemoveLRU();
                }
            }

            base[key] = value;
        }

        private void RemoveLRU() {
            object key = FirstKey;
            // be sure to call super.get(key), or you're likely to 
            // get infinite promotion recursion
            object value = base[key];

            Remove(key);

            ProcessRemovedLRU(key, value);
        }

        protected void ProcessRemovedLRU(object key, object value) {
        }

        public int MaximumSize {
            get { return _maximumSize; }
            set {
                _maximumSize = value;
                while (Count > _maximumSize)
                    RemoveLRU();
            }
        }

    }
}